home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / UNIX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-14  |  20.2 KB  |  1,027 lines

  1. #ifdef UNIX
  2. /*
  3.  * Timers and process delays work differently under POSIX.  The entire system
  4.  * is driven on a single select() call, which uses the timeout to detect alarms
  5.  * and the file descriptors to detect input.  An itimer is used to allow
  6.  * keyboard input to continue during lengthy activities --- which I tried to
  7.  * avoid for portability reasons, but it behaves *real* ugly otherwise.
  8.  * Especially when LakeSW.ampr.org lets 350K of SMTP mail pile up...
  9.  */
  10.  
  11. /* DO NOT allow this file to be optimized, since there is a bug in
  12.    GCC 4.6.x that causes code in ding() to DEVOUR CPU time */
  13.  
  14.  
  15. #ifndef _lint
  16. #define J_FREE_HACK 1    /* this eliminates a compiler warning */
  17. #endif
  18.  
  19. #include "global.h"
  20. #include "ctype.h"
  21. #ifdef linux
  22. #undef IS_LITTLE_ENDIAN    /* to avoid a re-definition warning */
  23. #endif
  24. #include <sys/stat.h>
  25. #include <sys/wait.h>
  26. #include <signal.h>
  27. #include "hardware.h"
  28. #include "commands.h"
  29. #ifndef _SYS_TIME_H
  30. #include <sys/time.h>
  31. #endif
  32. #include "timer.h"
  33. #include "proc.h"
  34. #include "socket.h"
  35. #include "session.h"
  36. #ifdef ALPHATEST
  37. #include "main.h"
  38. #endif
  39.  
  40. #ifdef NO_GETTOD
  41. #include <sys/timeb.h>
  42. #endif
  43.  
  44. #if !defined(_lint)
  45. static char rcsid[] OPTIONAL = "$Id: unix.c,v 1.29 1997/09/14 14:37:46 root Exp root $";
  46. #endif
  47.  
  48. /* and undo a collision avoidance, since we need the real one */
  49. #undef malloc
  50. #undef free
  51. #if 0    /* shouldn't need - should be in stdlib */
  52. extern void *malloc (size_t);
  53. extern void free (void *);
  54. #endif
  55.  
  56. #ifdef SETPSINFO
  57. int tnos_putenv (const char *envstr);
  58. void fix_env (void);
  59. #endif
  60. static void deinit_tick(void);
  61.  
  62. /* some versions of GNU libc (at least some for Linux) have a bad bug
  63.    that once it happens, a call to __libc_free() never returns. These
  64.    two variables (along with code in ding() and j_free()) are here to
  65.    keep this from disabling a system indefinitely. If a call to free
  66.    takes longer than 60 seconds to return, then TNOS is exited.
  67.  */
  68.  
  69. static int within_a_free_call = 0;
  70. static int time_in_a_free_call = 0;
  71. #define MAX_TIME_INA_FREE_CALL    60
  72.  
  73.  
  74. /* Don't use this yet... something's still calling malloc() directly */
  75. #undef LMCHECK            /* TEST memory allocation checker */
  76.  
  77. struct io
  78. {
  79.     struct io *next;
  80.     int fd;
  81.     void *event;
  82. };
  83.  
  84. char Hashtab[256];
  85. volatile int Tick;
  86. int Keyboard;
  87. volatile int32 Clock;
  88. extern struct timer *Timers;
  89.  
  90. static int __istate = 1;
  91. static struct timeval Starttime;
  92. static struct io *Events;
  93. #ifdef SHELL
  94. static int Shell;
  95. #endif
  96.  
  97.  
  98. /*****************************************************************************\
  99. *          Miscellanous functions not found in Unix              *
  100. \*****************************************************************************/
  101.  
  102.  
  103. unsigned long
  104. filelength(fd)
  105. int fd;
  106. {
  107. static struct stat sb;
  108.  
  109.     if (fstat (fd, &sb) == -1)
  110.         return 0;
  111.     return (unsigned long) sb.st_size;
  112. }
  113.  
  114.  
  115. #ifdef NEED_STRCASECMP
  116.  
  117. int
  118. strcasecmp(s1, s2)
  119. register char *s1, *s2;
  120. {
  121.     while (*s1 && *s2 && tolower (*s1) == tolower (*s2))
  122.         s1++, s2++;
  123.     return (tolower (*s1) - tolower (*s2));
  124. }
  125.  
  126. #endif
  127.  
  128.  
  129. #ifdef NEED_STRNCASECMP
  130.  
  131. int
  132. strncasecmp(s1, s2, n)
  133. register char *s1, *s2;
  134. int n;
  135. {
  136.     while (n && *s1 && *s2 && tolower (*s1) == tolower (*s2))
  137.         s1++, s2++, n--;
  138.     return ((n) ? (tolower (*s1) - tolower (*s2)) : 0);
  139. }
  140.  
  141. #endif
  142.  
  143.  
  144. char *
  145. strupr(s)
  146. char *s;
  147. {
  148. register char *p = s;
  149.  
  150.     while (*p)
  151.         *p = (char) toupper (*p), p++;
  152.     return s;
  153. }
  154.  
  155.  
  156. char *
  157. strlwr(s)
  158. char *s;
  159. {
  160. register char *p = s;
  161.  
  162.     while (*p)
  163.         *p = (char) tolower (*p), p++;
  164.     return s;
  165. }
  166.  
  167.  
  168. char *
  169. stpcpy(d, s)
  170. register char *d;
  171. register const char *s;
  172. {
  173.     while (*s)
  174.         *d++ = *s++;
  175.     *d = '\0';
  176.     return d;
  177. }
  178.  
  179.  
  180. char *
  181. itoa(n, buf, base)
  182. int n, base;
  183. char *buf;
  184. {
  185.     if (base != 10)
  186.         tprintf ("WARNING: itoa() passed radix %d\n", base);
  187.     sprintf (buf, "%d", n);
  188.     return buf;
  189. }
  190.  
  191.  
  192. /* This was in assembler, I assume for speed. */
  193.  
  194. int16
  195. hash_ip(ipaddr)
  196. uint32 ipaddr;
  197. {
  198. int h;
  199.  
  200.     h = ((ipaddr >> 16) & 0xFFFF) ^ (ipaddr & 0xFFFF);
  201.     return (int16) (Hashtab[((h >> 8) & 0xFF) ^ (h & 0xFF)]);    /*lint !e702 !e571 */
  202. }
  203.  
  204. /*****************************************************************************\
  205. *                Memory interface                  *
  206. \*****************************************************************************/
  207.  
  208. #ifdef LMCHECK
  209.  
  210. /*
  211.  * We track memory allocation via hash buckets.  This is a fixed-size hash
  212.  * table with variable-sized buckets:  we hash an address by taking some bits
  213.  * from it, and store the result in a slot in the bucket.
  214.  */
  215.  
  216. #define NMWHASH        4096    /* number of hash buckets - s/b power of 2 */
  217. #define LOGNMWH        12    /* log2(NMWHASH) */
  218. #define NMWHSHIFT    8    /* ptr shift for hashing */
  219. #define NMWHSLOT    32    /* initial slots in bucket */
  220.  
  221. struct hbucket
  222. {
  223.     void **ptr;
  224.     int nptr;
  225. };
  226.  
  227. static struct hbucket MWhashtab[NMWHASH];
  228.  
  229. static void
  230. mwhash(void *p)
  231. {
  232. register struct hbucket *h;
  233. int i;
  234.  
  235.     h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
  236.     if (!h->nptr)    {
  237.         h->ptr = malloc (NMWHSLOT * sizeof *h->ptr);
  238.         memset (h->ptr, 0, NMWHSLOT * sizeof *h->ptr);
  239.         i = 0;
  240.     } else {
  241.         for (i = 0; i < h->nptr; i++)    {
  242.             if (!h->ptr[i])
  243.                 break;
  244.         }
  245.         if (i == h->nptr)    {
  246.             h->ptr = realloc (h->ptr, (h->nptr + NMWHSLOT) * sizeof *h->ptr);
  247.             memset (h->ptr + h->nptr, 0, NMWHSLOT * sizeof *h->ptr);
  248.             h->nptr += NMWHSLOT;
  249.         }
  250.     }
  251.     h->ptr[i] = p;
  252. }
  253.  
  254.  
  255. static int
  256. mwunhash(void *p)
  257. {
  258. register struct hbucket *h;
  259. int i;
  260.  
  261.     h = MWhashtab + (((unsigned long) p >> NMWHSHIFT) & (NMWHASH - 1));
  262.     for (i = h->nptr; i--; )    {
  263.         if (h->ptr[i] == p)
  264.             break;
  265.     }
  266.     if (i == -1)
  267.         return 0;
  268.     h->ptr[i] = 0;
  269.     return 1;
  270. }
  271. #endif
  272.  
  273.  
  274. void *
  275. mallocw(unsigned size)
  276. {
  277. void *p;
  278. int waited = 0;
  279.  
  280.     while ((p = malloc(size)) == (void *)0)    {
  281.         kpause (1000);
  282.         if (++waited > 150)
  283.             where_outta_here(1, "mallocw");
  284.     }
  285. #ifdef LMCHECK
  286.     mwhash(p);
  287. #endif
  288.     return p;
  289. }
  290.  
  291.  
  292. void *
  293. callocw(cnt, size)
  294. unsigned cnt, size;
  295. {
  296. void *p;
  297.  
  298.     p = mallocw (size * cnt);
  299.     memset(p, 0, size * cnt);
  300.     return p;
  301. }
  302.  
  303.  
  304.  
  305. static jmp_buf free_trap;
  306.  
  307.  
  308. static void
  309. j_free_trap (int sig OPTIONAL)
  310. {
  311.     ++Ksig.kfreesegvs;
  312.     longjmp (free_trap, 1);
  313. }
  314.  
  315.  
  316.  
  317. void
  318. j_free(IFLINT(const) void *p)
  319. {
  320. struct sigaction sa, saold;
  321.  
  322.     if (p)    {
  323. #ifdef LMCHECK
  324.         if (!mwunhash (p))    {
  325.             printf("\r\7WARNING: free()ing unknown pointer %lx\r\n", (unsigned long) p);
  326.             return;
  327.         }
  328. #endif
  329.         time_in_a_free_call = 0;
  330.         within_a_free_call = 1;
  331.  
  332.         /* protect free() from SEGV signals */
  333.         sa.sa_handler = j_free_trap;
  334.         sa.sa_flags = 0;
  335.         (void) sigaction (SIGSEGV, &sa, &saold);
  336.  
  337.         if (setjmp (free_trap) == 0)
  338.             free((void *)p);
  339.  
  340.         /* restore previous value for SIGV signals */
  341.         (void) sigaction (SIGSEGV, &saold, (struct sigaction *) 0);
  342.         within_a_free_call = 0;
  343.     }
  344. }
  345.  
  346.  
  347.  
  348. /*****************************************************************************\
  349. *            Interrupt management - null                  *
  350. \*****************************************************************************/
  351.  
  352. int
  353. istate()
  354. {
  355.     return __istate;
  356. }
  357.  
  358.  
  359. int
  360. disable ()
  361. {
  362. sigset_t s;
  363. int ops;
  364.  
  365.     if (__istate)    {
  366.         (void) sigemptyset (&s);
  367.         (void) sigaddset (&s, SIGALRM);
  368.         (void) sigprocmask (SIG_BLOCK, &s, (sigset_t *) 0);
  369.     }
  370.     ops = __istate;
  371.     __istate = 0;
  372.     return ops;
  373. }
  374.  
  375. int
  376. enable (void)
  377. {
  378.     restore (1);
  379.     return 0;
  380. }
  381.  
  382. void
  383. restore(prs)
  384. int prs;
  385. {
  386. sigset_t s;
  387.  
  388.     if (__istate != prs)    {
  389.         (void) sigemptyset (&s);
  390.         (void) sigaddset (&s, SIGALRM);
  391.         (void) sigprocmask ((prs? SIG_UNBLOCK: SIG_BLOCK), &s, (sigset_t *) 0);
  392.     }
  393.     __istate = prs;
  394. }
  395.  
  396.  
  397. /*****************************************************************************\
  398. *                  Date and time functions                  *
  399. \*****************************************************************************/
  400.  
  401. long
  402. secclock()
  403. {
  404. #ifdef NO_GETTOD
  405. static struct timeb t;
  406.  
  407.     ftime (&t);
  408.     return t.time - Starttime.tv_sec - (Starttime.tv_usec > t.millitm * 1000);
  409. #else
  410. static struct timezone tz;
  411. static struct timeval tv;
  412.  
  413.     (void) gettimeofday (&tv, &tz);
  414.     return tv.tv_sec - Starttime.tv_sec - (Starttime.tv_usec > tv.tv_usec);        /*lint !e514 */
  415. #endif
  416. }
  417.  
  418.  
  419. long
  420. msclock()
  421. {
  422. #ifdef NO_GETTOD
  423. static struct timeb t;
  424.  
  425.     ftime (&t);
  426.     t.millitm *= 1000;
  427.     if (t.millitm < Starttime.tv_usec)    {
  428.         t.millitm += 1000000;
  429.         t.time--;
  430.     }
  431.     return (t.time - Starttime.tv_sec) * 1000 +
  432.         (t.millitm - Starttime.tv_usec) / 1000;
  433. #else
  434. static struct timezone tz;
  435. static struct timeval tv;
  436.  
  437.     (void) gettimeofday (&tv, &tz);
  438.     if (tv.tv_usec < Starttime.tv_usec)    {
  439.         tv.tv_usec += 1000000;
  440.         tv.tv_sec--;
  441.     }
  442.     return (tv.tv_sec - Starttime.tv_sec) * 1000 +
  443.         (tv.tv_usec - Starttime.tv_usec) / 1000;
  444. #endif
  445. }
  446.  
  447.  
  448. static void
  449. init_time(void)
  450. {
  451. #ifdef NO_GETTOD
  452. struct timeb t;
  453.  
  454.     ftime (&t);
  455.     Starttime.tv_sec = t.time;
  456.     Starttime.tv_usec = t.millitm * 1000;
  457. #else
  458. struct timezone tz;
  459.  
  460.     (void) gettimeofday (&Starttime, &tz);
  461. #endif
  462. }
  463.  
  464.  
  465. void
  466. gettime(tp)
  467. struct time *tp;
  468. {
  469. struct tm *tm;
  470. #ifdef NO_GETTOD
  471. static struct timeb tb;
  472.  
  473.     ftime (&tb);
  474.     tm = localtime (&tb.time);
  475.     tp->ti_hund = tb.millitm / 10;
  476. #else
  477. static struct timeval tv;
  478. static struct timezone tz;
  479.  
  480.     (void) gettimeofday (&tv, &tz);
  481.     tm = localtime ((const time_t *)&tv.tv_sec);
  482.     tp->ti_hund = tv.tv_usec / 10000;
  483. #endif
  484.     tp->ti_hour = tm->tm_hour;
  485.     tp->ti_min = tm->tm_min;
  486.     tp->ti_sec = tm->tm_sec;
  487. }
  488.  
  489.  
  490. void
  491. tnos_getdate(dp)
  492. struct date *dp;
  493. {
  494. struct tm *tm;
  495. #ifdef NO_GETTOD
  496. static struct timeb tb;
  497.  
  498.     ftime (&tb);
  499.     tm = localtime (&tb.time);
  500. #else
  501. static struct timeval tv;
  502. static struct timezone tz;
  503.  
  504.     (void) gettimeofday (&tv, &tz);
  505.     tm = localtime ((const time_t *)&tv.tv_sec);
  506. #endif
  507.     dp->da_year = tm->tm_year + 1900;
  508.     if (dp->da_year < 1970)
  509.         dp->da_year += 100;
  510.     dp->da_mon = tm->tm_mon + 1;
  511.     dp->da_day = tm->tm_mday;
  512. }
  513.  
  514.  
  515. long
  516. dostounix(dp, tp)
  517. struct date *dp;
  518. struct time *tp;
  519. {
  520. static struct tm tm;
  521. struct tm *tx;
  522. long now;
  523.  
  524.     tm.tm_year = dp->da_year - 1900;
  525.     tm.tm_mon = dp->da_mon - 1;
  526.     tm.tm_mday = dp->da_day;
  527.     tm.tm_hour = tp->ti_hour;
  528.     tm.tm_min = tp->ti_min;
  529.     tm.tm_sec = tp->ti_sec;
  530.     /* This desperately needs to be fixed.  How? */
  531.     (void) time (&now);
  532.     tx = localtime (&now);
  533.     tm.tm_isdst = tx->tm_isdst;
  534.     return mktime (&tm);
  535. }
  536.  
  537.  
  538. /*****************************************************************************\
  539. *                Timers, I/O and scheduling                  *
  540. \*****************************************************************************/
  541.  
  542. void
  543. register_io(fd, event)
  544. int fd;
  545. void *event;
  546. {
  547. struct io *evp;
  548.  
  549.     if ((evp = mallocw (sizeof *evp)) == (struct io *)0)    {
  550.         tputs ("register_io: no memory for event\n");
  551.         where_outta_here (1, "register_io");
  552.     }
  553.     evp->fd = fd;
  554.     evp->event = event;
  555.     evp->next = Events;
  556.     Events = evp;
  557. }
  558.  
  559.  
  560. void
  561. unregister_io(fd)
  562. int fd;
  563. {
  564. struct io *evp, *evc;
  565.  
  566.     for (evp = 0, evc = Events; evc->fd != fd; evp = evc, evc = evc->next)
  567.         ;
  568.     if (!evc)    {
  569.         tputs ("unregister_io: unknown fd\n");
  570.         return;
  571.     }
  572.     if (evp)
  573.         evp->next = evc->next;
  574.     else
  575.         Events = evc->next;
  576.     j_free (evc);
  577. }
  578.  
  579.  
  580. #ifndef DUMP_CORE
  581. #ifdef ALPHATEST
  582. extern void proc_launch (void);
  583. #endif
  584.  
  585. static void
  586. ouch(int sig OPTIONAL)
  587. {
  588. struct sigaction sa;
  589.  
  590.     sa.sa_handler = SIG_DFL;
  591.     sa.sa_flags = 0;
  592.     (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
  593. #ifdef SIGBUS
  594.     (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
  595. #endif
  596.  
  597. #if 0
  598.     if (fork() == 0)    {
  599.         sigaction(sig, &sa, (struct sigaction *) 0);
  600.         (void) kill(getpid(), sig);
  601.     }
  602.     detach_all_asy();
  603. #endif
  604.  
  605.     if (shall_we_crash())
  606.         crash_it_already ("SIGSEGV signal");
  607. #ifdef ALPHATEST
  608.     if (++Ksig.kresumes == RESTART_COUNT || Command->proc == Curproc)
  609.         exit (1);
  610.  
  611.     /* Stop alarm clock in case it's running */
  612.     stop_timer (&Curproc->alarm);
  613.  
  614.     /* attempt to simply kill off the process running, not TNOS */
  615.     if (main_exit != TRUE)    {
  616.         time_t now;
  617.         
  618.         log (-1, "signal SIGSEGV caught - killing process '%s' and resuming",
  619.             Curproc->name);
  620.         now = time ((time_t *)0);
  621.         tcmdprintf ("*** signal SIGSEGV caught at %s*** killing process '%s' and resuming\n",
  622.             ctime (&now), Curproc->name);
  623.         tprintf ("\n!!! System error occurred !!!\n");
  624.     }
  625.     /* these were done without a signal handler, to allow dying if logging fails */
  626.  
  627.     /* reset the handler */
  628.     sa.sa_handler = ouch;
  629.     sa.sa_flags = 0;
  630.     (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
  631. #ifdef SIGBUS
  632.     (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
  633. #endif
  634.     switch (Curproc->ptype)    {
  635.         case PTYPE_IO:
  636.         case PTYPE_DAEMON:
  637.         case PTYPE_SERVER:    Ksig.krestarts++;
  638.                     if (main_exit == TRUE)
  639.                         killself ();
  640.                     else
  641.                         proc_launch ();        /* restart the process ;-) */
  642.                     break;
  643.         case PTYPE_NORMAL:
  644.         default:        if (main_exit != TRUE)    {
  645.                         tflush ();
  646.                         kpause (3000);
  647.                     }
  648.                     killself ();        /* let the errant process be the martyr */
  649.     }
  650. #endif
  651. }
  652. #endif
  653.  
  654.  
  655. static void
  656. ding(int i)
  657. {
  658. static struct timeval tv;
  659. long oclock;
  660. struct timeval *tvp;        /*lint -esym(550,tvp) */
  661. #ifndef _lint
  662. static fd_set fds;
  663. struct io *evp;
  664. #endif
  665.  
  666.     /* first a check for a locked up call to free() */
  667.     if (within_a_free_call)    {
  668.         if (++time_in_a_free_call > MAX_TIME_INA_FREE_CALL)    {
  669.             within_a_free_call = 0;
  670.             where_outta_here(3, "a libc free() lockup");
  671.         }
  672.     }
  673.     
  674.     /* do pending output */
  675.     if (!i)        {
  676.         tflush();
  677.         rflush();
  678.     }
  679.     /* collect input events to wait on */
  680. #ifndef _lint
  681.     FD_ZERO(&fds);
  682.     for (evp = Events; evp; evp = evp->next)
  683.         FD_SET(evp->fd, &fds);
  684. #endif
  685.     /* get time until next timer; if zero, fake a very large one */
  686.     /* if we have a nonzero argument, we're a timer tick; poll, don't block */
  687.     if (i)    {
  688.         tv.tv_sec = tv.tv_usec = 0;
  689.         tvp = &tv;
  690.     } else if (!Timers)
  691.         tvp = 0;
  692.     else {
  693.         /* This section gets improperly optimized in GCC 4.6.x */
  694.         tv.tv_sec = (Timers->expiration - Clock) * MSPTICK;
  695.         if (tv.tv_sec <= 0)
  696.             tv.tv_sec = 0;
  697.         tv.tv_usec = (tv.tv_sec % 1000) * 1000;
  698.         tv.tv_sec /= 1000;
  699.         tvp = &tv;
  700.     }
  701.     /* check for I/O */
  702. #ifndef _lint
  703.     select (FD_SETSIZE, &fds, 0, 0, tvp);
  704.     /* signal events for pending I/O */
  705.     for (evp = Events; evp; evp = evp->next)    {
  706.         if (FD_ISSET(evp->fd, &fds))
  707.             ksignal (evp->event, 1);
  708.     }
  709. #endif
  710.     /* run any due timers */
  711.     ksignal ((volatile void *) &Tick, 1);
  712.     /* and update the system time */
  713.     oclock = Clock;
  714.     Clock = msclock() / MSPTICK;
  715.     Tick = Clock - oclock;
  716. }
  717.  
  718.  
  719. static void
  720. init_tick(void)
  721. {
  722. struct sigaction sa;
  723. struct itimerval it;
  724.  
  725.     sa.sa_flags = 0;
  726.     sa.sa_handler = ding;
  727.     (void) sigaction (SIGALRM, &sa, (struct sigaction *) 0);
  728.     it.it_interval.tv_sec = 0;
  729.     it.it_interval.tv_usec = MSPTICK * 1000;
  730.     it.it_value = it.it_interval;
  731.     (void) setitimer (ITIMER_REAL, &it, (struct itimerval *) 0);
  732. }
  733.  
  734.  
  735. static void
  736. deinit_tick(void)
  737. {
  738. struct itimerval it;
  739.  
  740.     it.it_interval.tv_sec = it.it_interval.tv_usec = 0;
  741.     it.it_value = it.it_interval;
  742.     (void) setitimer (ITIMER_REAL, &it, (struct itimerval *) 0);
  743. }
  744.  
  745.  
  746. static void
  747. cleanup (int sig OPTIONAL)
  748. {
  749.     where_outta_here (0, "cleanup");
  750. }
  751.  
  752.  
  753. void
  754. init_sys(int no_itimer)
  755. {
  756. struct sigaction sa;
  757.  
  758.     init_time();
  759.     register_io (0, &Keyboard);
  760.  
  761. #ifndef DUMP_CORE
  762.     sa.sa_handler = ouch;
  763.     sa.sa_flags = 0;
  764.     (void) sigaction (SIGSEGV, &sa, (struct sigaction *) 0);
  765. #ifdef SIGBUS
  766.     (void) sigaction (SIGBUS, &sa, (struct sigaction *) 0);
  767. #endif
  768. #endif /* DUMP_CORE */
  769.  
  770.     sa.sa_handler = cleanup;
  771.     sa.sa_flags = 0;
  772.     (void) sigaction (SIGTERM, &sa, (struct sigaction *) 0);
  773.  
  774.     sa.sa_handler = SIG_IGN;
  775.     sa.sa_flags = 0;
  776.     (void) sigaction (SIGWINCH, &sa, (struct sigaction *) 0);
  777.     if (!no_itimer)
  778.         init_tick();
  779. }
  780.  
  781.  
  782. void
  783. deinit_sys()
  784. {
  785.     deinit_tick();
  786.     unregister_io(0);
  787. }
  788.  
  789.  
  790. void
  791. giveup()
  792. {
  793.     /* suspend heartbeat */
  794.     deinit_tick();
  795.     /* block for I/O */
  796.     ding (0);
  797.     /* and reactivate the tick */
  798.     init_tick();
  799. }
  800.  
  801.  
  802.  
  803. #ifdef SETPSINFO
  804.  
  805. static char **tnos_envp = NULLCHARP;
  806. static int tnos_envp_size = 0;
  807.  
  808. static int
  809. find_env (const char *lookfor)
  810. {
  811. char **env;
  812. unsigned int len;
  813. int theindex = 0;
  814.  
  815.     len = strlen (lookfor);
  816.     for (env = tnos_envp; env && *env; env++, theindex++)    {
  817.         if (!strncmp (lookfor, *env, len) && (*env)[len] == '=')
  818.             return theindex;
  819.     }
  820.     return -1;
  821. }
  822.  
  823.  
  824. static int
  825. _putenv (const char *envstr)
  826. {
  827. char **new_envp;
  828.  
  829.     new_envp = (char **) callocw ((unsigned int)(tnos_envp_size + 2), sizeof (char *));
  830.     if (new_envp == NULLCHARP)
  831.         return -1;
  832.  
  833.     memcpy (new_envp, tnos_envp, (size_t) ((unsigned int)tnos_envp_size * sizeof (char *)));
  834.     new_envp[tnos_envp_size++] = strdup (envstr);
  835.     free (tnos_envp);
  836.     tnos_envp = new_envp;
  837.     return 0;
  838. }
  839.  
  840.  
  841.  
  842. int
  843. tnos_putenv (const char *envstr)
  844. {
  845. char *cp;
  846. unsigned int len;
  847.  
  848.     /* sanity checking */
  849.     if (!envstr || !*envstr || (cp = strchr (envstr, '=')) == NULLCHAR)
  850.         return -1;
  851.  
  852.     /* look to see if the entry already exists, if so, error */
  853.     len = (unsigned int) (cp - envstr);
  854.     cp = (char *) malloc (len + 1);
  855.     if (cp == NULLCHAR)
  856.         return -1;
  857.     strncpy (cp, envstr, len);
  858.     if (find_env (cp) != -1)
  859.         return -1;
  860.     free (cp);
  861.     
  862.     /* add new entry in the environment */
  863.     return _putenv (envstr);
  864. }
  865.  
  866.  
  867. #if 0
  868.  
  869. char *
  870. getenv (const char *lookfor)
  871. {
  872. char **env = tnos_envp;
  873. unsigned int len;
  874. int theindex;
  875.  
  876.     len = strlen (lookfor);
  877.     theindex = find_env (lookfor);
  878.     
  879.     if (theindex != -1)
  880.         return (env[theindex] + (len + 1));
  881. #if 0
  882.         return (*env + (len + 1));
  883. #endif
  884.     return NULLCHAR;
  885. }
  886.  
  887.  
  888.  
  889. int
  890. setenv (const char *name, const char *value, int overwrite)
  891. {
  892. int theindex;
  893. char *buf;
  894. int retval = 0;
  895.  
  896.     /* create the new entry */
  897.     buf = (char *) callocw (1, strlen(name) + strlen(value) + 2);
  898.     if (buf == NULLCHAR)
  899.         return -1;
  900.     sprintf (buf, "%s=%s", name, value);
  901.  
  902.     /* see if thie entry already exists */
  903.     theindex = find_env (name);
  904.     if (theindex == -1)    {    /* new entry */
  905.         retval = _putenv (buf);
  906.         free (buf);
  907.     } else    {            /* entry exists */
  908.         if (overwrite)    {
  909.             free (tnos_envp[theindex]);
  910.             tnos_envp[theindex] = buf;
  911.         } else
  912.             free (buf);
  913.     }
  914.     return retval;
  915. }
  916.  
  917.  
  918. void
  919. unsetenv (const char *name)
  920. {
  921. int theindex;
  922.  
  923.     while ((theindex = find_env (name)) != -1)    {
  924.         free (tnos_envp[theindex]);
  925.  
  926.         do    {
  927.             tnos_envp[theindex] = tnos_envp[theindex + 1];
  928.         } while (tnos_envp[++theindex]);
  929.         tnos_envp_size--;
  930.     }
  931. }
  932. #else
  933. #if !defined (__ELF__)
  934. #undef __environ
  935. #ifndef _lint
  936. #define __environ       environ
  937. #endif
  938. #endif
  939.  
  940. #ifndef _lint
  941. extern char **__environ;
  942. #endif
  943.  
  944.  
  945. void
  946. fix_env (void)
  947. {
  948.  
  949.     __environ = tnos_envp;
  950. }
  951. #endif
  952. #endif
  953.  
  954. #ifdef SHELL
  955.  
  956. int
  957. doshell(int argc, char **argv, void *p OPTIONAL)
  958. {
  959. struct sigaction sa, old_int, old_quit;
  960. int ac, pid;
  961. int pi[2];
  962. char const *av[4];
  963.  
  964.     /*
  965.      * Under *ix, one would expect ! or shell to work like in other *ix
  966.      * programs.  Since we don't really want to emulate DOS doshell()'s
  967.      * special handling for argv[1] == "/c" anyway :-) we will handle
  968.      * this properly.
  969.      *
  970.      * argc < 2: ${SHELL:-/bin/sh}
  971.      * >= 2: concatenate and /bin/sh -c it (NOT $SHELL)!
  972.      */
  973.     if (!sm_usestdio() || (Curproc->input != Command->input))    {
  974.         tputs ("Not running on TNOS console\n");
  975.         return 1;
  976.     }
  977.     if (pipe(pi) == -1)    {
  978.         tputs ("Can't create pipe for subprocess\n");
  979.         return 1;
  980.     }
  981.     switch (pid = fork())    {
  982.         case -1:
  983.             tputs ("Fork failed\n");
  984.             return 1;
  985.         case 0:
  986.             close (pi[0]);
  987.             ac = 1;
  988.             if (argc > 1 || (av[0] = getenv ("SHELL")) == NULLCHAR)
  989.                 av[0] = "/bin/sh";
  990.             if (argc > 1)    {
  991.                 av[ac++] = "-c";
  992.                 av[ac++] = argv[1];
  993.             }
  994.             av[ac] = 0;
  995.             (void) execve (av[0], (char * const *)av, (char * const *)tnos_envp);    /*lint !e605 */
  996.             _exit(1);
  997.         default:
  998.             close (pi[1]);
  999.             iosuspend();
  1000.             unregister_io (0);
  1001.             register_io (pi[0], &Shell);
  1002.             /* signal handling... */
  1003.             (void) sigemptyset (&sa.sa_mask);
  1004.             sa.sa_flags = 0;
  1005.             sa.sa_handler = SIG_IGN;
  1006.             (void) sigaction (SIGINT, &sa, &old_int);
  1007.             (void) sigaction (SIGQUIT, &sa, &old_quit);
  1008.             kwait (&Shell);
  1009.             (void) sigaction (SIGQUIT, &old_quit, 0);
  1010.             (void) sigaction (SIGINT, &old_int, 0);
  1011.             unregister_io (pi[0]);
  1012.             close (pi[0]);
  1013.             register_io (0, &Keyboard);
  1014.             ioresume();
  1015.             ac = 0;
  1016.             /* this SHOULD take care of clearing vombie processes */
  1017.             (void) waitpid (pid, &ac, WNOHANG);
  1018.             swapscreen(NULLSESSION, Command);
  1019.     }
  1020.     return 0;
  1021. }
  1022.  
  1023. #endif        /* SHELL */
  1024.  
  1025. #endif        /* UNIX */
  1026.  
  1027.